package com.ssm.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.ssm.subject.common.entity.PageResult;
import com.ssm.subject.common.enums.IsDeletedFlagEnum;
import com.ssm.subject.common.enums.SubjectLikedStatusEnum;
import com.ssm.subject.common.util.LoginUtil;
import com.ssm.subject.domain.bo.SubjectLikedBO;
import com.ssm.subject.domain.bo.SubjectLikedMessage;
import com.ssm.subject.domain.convert.SubjectLikedBOConvert;
import com.ssm.subject.domain.redis.RedisUtil;
import com.ssm.subject.domain.service.SubjectLikedDomainService;
import com.ssm.subject.infra.basic.entity.SubjectInfo;
import com.ssm.subject.infra.basic.entity.SubjectLiked;
import com.ssm.subject.infra.basic.service.SubjectInfoService;
import com.ssm.subject.infra.basic.service.SubjectLikedService;
import lombok.extern.log4j.Log4j2;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
@Log4j2
public class SubjectLikedDomainServiceImpl implements SubjectLikedDomainService {

    @Resource
    private SubjectLikedService subjectLikedService;

    @Resource
    private RedisUtil redisUtil;

    /**
     * 点赞hash的总key
     */
    private static final String SUBJECT_LIKED_KEY = "subject.liked";

    /**
     * 题目点赞数key前缀
     */
    private static final String SUBJECT_LIKED_COUNT_KEY = "subject.liked.count";

    /**
     * 题目点赞人key前置
     */
    private static final String SUBJECT_LIKED_DETAIL_KEY = "subject.liked.detail";

    @Resource
    private SubjectInfoService subjectInfoService;


    @Resource
    private RocketMQTemplate rocketMQTemplate;
    /**
     * 新增/取消点赞
     * @return
     */
    @Override
    public void add(SubjectLikedBO subjectLikedBO) {
        String likeUserId = subjectLikedBO.getLikeUserId();
        Long subjectId = subjectLikedBO.getSubjectId();
        Integer status = subjectLikedBO.getStatus();

//        String hashKey = buildSubjectLikedKey(subjectId.toString(), likeUserId);
//        redisUtil.putHash(SUBJECT_LIKED_KEY, hashKey, status);

        //将每次的点赞消息发送到mq中直接与数据库交互，替换redis-hash表
        SubjectLikedMessage subjectLikedMessage = new SubjectLikedMessage();
        subjectLikedMessage.setSubjectId(subjectId);
        subjectLikedMessage.setLikeUserId(likeUserId);
        subjectLikedMessage.setStatus(status);
        rocketMQTemplate.convertAndSend("subject-liked", JSON.toJSONString(subjectLikedMessage));

        String countKey = SUBJECT_LIKED_COUNT_KEY + "." + subjectId;
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + likeUserId;
        if(SubjectLikedStatusEnum.LIKED.getCode() == status) { //点赞状态
            redisUtil.increment(countKey, 1);
            redisUtil.set(detailKey, "1"); //value用1标记
        } else {
            Integer count = redisUtil.getInt(countKey);
            if(Objects.isNull(count) || count <= 0) { //当数量不存在或为0时直接结束
                return;
            }
            redisUtil.increment(countKey, -1);
            redisUtil.del(detailKey);
        }
        ;
    }


    /**
     * 判断当前用户是否点赞
     */
    @Override
    public Boolean isLiked(String subjectId, String userId) {
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + userId;
        return redisUtil.exist(detailKey);
    }

    /**
     * 获取题目点赞数量
     */
    @Override
    public Integer getLikedCount(String subjectId) {
        String countKey = SUBJECT_LIKED_COUNT_KEY + "." + subjectId;
        Integer count = redisUtil.getInt(countKey);
        if(Objects.isNull(count) || count <= 0) {
            count = 0;
        }
        return count;
    }

    /**
     * 数据库同步redis点赞数据
     */
    @Override
    public void syncLiked() {
        Map<Object, Object> subjectLikedMap = redisUtil.getHashAndDelete(SUBJECT_LIKED_KEY);
        if(log.isInfoEnabled()) {
            log.info("syncLiked.subjectLikedMap:{}", JSON.toJSONString(subjectLikedMap));
        }
        if(subjectLikedMap.isEmpty()) {
            return;
        }

        //批量同步数据库
        List<SubjectLiked> subjectLikedList = new ArrayList<>();
        subjectLikedMap.forEach((key, val) -> {
            SubjectLiked subjectLiked = new SubjectLiked();
            String[] split = key.toString().split(":"); //subjectId:userId
            subjectLiked.setSubjectId(Long.valueOf(split[0]));
            subjectLiked.setLikeUserId(split[1]);
            subjectLiked.setStatus(Integer.valueOf(val.toString()));
            subjectLiked.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            subjectLikedList.add(subjectLiked);
        });

        subjectLikedService.batchInsertOrUpdate(subjectLikedList);
    }

    /**
     * 分页查询点赞记录
     * @param subjectLikedBO
     * @return
     */
    @Override
    public PageResult<SubjectLikedBO> getSubjectLikedPage(SubjectLikedBO subjectLikedBO) {
        PageResult<SubjectLikedBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectLikedBO.getPageNo());
        pageResult.setPageSize(subjectLikedBO.getPageSize());
        int start = (subjectLikedBO.getPageNo() - 1) * subjectLikedBO.getPageSize();
        SubjectLiked subjectLiked = SubjectLikedBOConvert.INSTANCE.subjectLikedBoToSubjectLiked(subjectLikedBO);
        subjectLiked.setLikeUserId(LoginUtil.getLoginId());
        int count = subjectLikedService.countByCondition(subjectLiked);
        if(count == 0) {
            return pageResult;
        }
        List<SubjectLiked> subjectLikedList = subjectLikedService.queryPage(subjectLiked, start, subjectLikedBO.getPageSize());
        List<SubjectLikedBO> subjectLikedBOList = SubjectLikedBOConvert.INSTANCE.subjectLikedsToBos(subjectLikedList);
        subjectLikedBOList.forEach(info -> {
            SubjectInfo subjectInfo = subjectInfoService.queryById(info.getSubjectId());
            info.setSubjectName(subjectInfo.getSubjectName());
        });

        pageResult.setRecords(subjectLikedBOList);
        pageResult.setTotal(count);
        return pageResult;
    }

    /**
     * 构建点赞hashKey
     */
    private String buildSubjectLikedKey(String subjectId, String likeUserId) {
        return subjectId + ":" + likeUserId;
    }


    @Override
    public void syncLikedMsg(SubjectLikedBO subjectLikedBO) {
        //同步到数据库
        SubjectLiked subjectLiked = new SubjectLiked();
        subjectLiked.setSubjectId(subjectLikedBO.getSubjectId());
        subjectLiked.setLikeUserId(subjectLikedBO.getLikeUserId());
        subjectLiked.setStatus(subjectLikedBO.getStatus());
        subjectLiked.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        List<SubjectLiked> subjectLikedList = new LinkedList<>();
        subjectLikedList.add(subjectLiked);
        subjectLikedService.batchInsertOrUpdate(subjectLikedList);
    }
}
